{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "CDO Tranche Pricing\n",
    "-------------------\n",
    "\n",
    "The par spread $S$ of a CDS tranche is given by\n",
    "$$S = \\frac{\\text{Protection Leg PV}}{\\text{RPV01}},$$\n",
    "\n",
    "where\n",
    "$$\\begin{aligned}\n",
    "\\text{RPV01} &= \\sum_{i} \\Delta_i Z(t_i) \\frac{Q(t_{i-1},K_1,K_2) + Q(t_i, K_1, K_2)}{2} \\\\\n",
    "\\text{Protection Leg PV} &= \\int_{0}^{T} Z(t) (-dQ(t,K_1,K_2))\n",
    "\\end{aligned}$$\n",
    "\n",
    "Here, \n",
    "\n",
    "* $K_1, K_2, T$ is the tranche starting level, final level, and maturity, respectively.\n",
    "* $Z(t)$ is the discount factor curve.\n",
    "* $Q(t,K_1,K_2)$ is the tranche survival curve: $Q(t,K_1,K_2)= 1 - \\frac{f(t, K_2) - f(t, K_1)}{K_2 - K_1}$\n",
    "* $t_i$ is the time of the $i^{th}$ premium payment. And $\\Delta_i$ is the time-fraction of the $i^{th}$\n",
    "  interval, using the Act365 DCF.\n",
    " \n",
    "  \n",
    "And $f(t,K) = E[ \\min (L(t),K)]$ is model-dependent.\n",
    "\n",
    "With the exception for the formula of $Q$, the CDO tranche pricing formula is identical to\n",
    "the CDS pricing formula with $R=0$. So we first define a class for calculating CDS's."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "from datetime import timedelta\n",
    "class CDS(object):\n",
    "    \"\"\"A generic CDS class. Can also be used for CDO tranches.\n",
    "    \n",
    "    Attributes:\n",
    "        today (datetime.date): The present date.\n",
    "        maturity (datetime.date): The maturity of the CDO.\n",
    "        remaining_payments (list): A list of datetime.date objects indicating \n",
    "            the remaining payment dates for the premium leg.\n",
    "        R (float): The recovery fraction (0 to 1).\n",
    "        Z (callable function): A function Z(t) that outputs the discount factor\n",
    "            Z(t) for a given time t (datetime.date object). Input and output are\n",
    "            both positive floats.\n",
    "        Q (callable function): A function Q(t) that takes in a single\n",
    "            datetime.date perameter and returns a float representing the tranche\n",
    "            survival probability. This function should be well-defined for all \n",
    "            dates between `today` and `maturity`.\n",
    "    \"\"\"\n",
    "    def __init__(self, today, maturity, remaining_payments, R, Z, Q):\n",
    "        self.today = today\n",
    "        self.maturity = maturity\n",
    "        self.remaining_payments = remaining_payments\n",
    "        self.R = R\n",
    "        self.Z = Z\n",
    "        self.Q = Q\n",
    "    def rpv01(self):\n",
    "        \"\"\"Returns the value of the tranche premium leg for unit notional.\n",
    "        \"\"\"\n",
    "        days = [self.today] + self.remaining_payments\n",
    "        print(days)\n",
    "        nodes = [(day - self.today).days / 365 for day in days]\n",
    "        #qvals = [self.Q(day) for day in days]\n",
    "        qvals = self.Q\n",
    "        total = 0\n",
    "        for i in range(1, len(days)):\n",
    "            delta = nodes[i] - nodes[i - 1]\n",
    "            total += delta * self.Z(days[i]) * (qvals[i] + qvals[i - 1])\n",
    "        return total / 2\n",
    "    def protectionLegPV(self, N = 200):\n",
    "        \"\"\"Returns the value of the protection leg for unit notional.\n",
    "        \n",
    "        Arguments:\n",
    "            N (int, optional): The number of nodes for calculating the integral.\n",
    "        \"\"\"\n",
    "        delta = (self.maturity - self.today).days / N\n",
    "        days = [today + timedelta(days = delta) * n for n in range(N + 1)]\n",
    "        #print(days)\n",
    "        #qvals = [self.Q(day) for day in days]\n",
    "        qvals = self.Q\n",
    "        values = [Z(days[i]) * (qvals[i - 1] - qvals[i])\n",
    "                  for i in range(1, len(days))]\n",
    "        return (1 - self.R) * sum(values)\n",
    "    def parSpread(self, N = 200):\n",
    "        \"\"\" Returns the par spread.\n",
    "        \n",
    "        Arguments:\n",
    "            N (int, optional): The number of nodes for calculating the \n",
    "                protection leg integral.\n",
    "        \"\"\"\n",
    "        return self.protectionLegPV(N) / self.rpv01()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Large Homogenous Portfolio (LHP) Model\n",
    "--------------------------------------\n",
    "\n",
    "The LHP tranche pricing model is given by the following equations:\n",
    "$$\\begin{aligned}\n",
    "E[\\min (L(T), K)] &= (1-R) \\Phi_{2}(C(T), -A(K), - \\beta) + K \\Phi(A(K)) \\\\\n",
    "A(K) &= \\frac{1}{\\beta} \\left( C(T) - \\sqrt{1 - \\beta^{2}} \\Phi^{-1} \\left( \\frac{K}{1-R} \\right) \\right) \\\\\n",
    "C(T) &= \\Phi^{-1} (1 - Q(T))\n",
    "\\end{aligned}$$\n",
    "\n",
    "Here:\n",
    "* $\\Phi_{2}$ is the cdf of the bivariate normal distribution. The third perameter being correlation.\n",
    "* $\\beta^{2}$ the correlation\n",
    "* $R$ is the recovery rate.\n",
    "* $Q(T)$ is the survival curve"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "from scipy.stats import norm, mvn #normal and bivariate normal\n",
    "from numpy       import sqrt\n",
    "\n",
    "def Q_lhp(t, K1, K2, R, beta, Q):\n",
    "    \"\"\"Calculates the Tranche survival curve for the LHP model.\n",
    "    \n",
    "    Args:\n",
    "        T (datetime.date): Should be given in \"days\" (no hours, minutes, etc.)\n",
    "        K1 (float): The starting value of the tranche. Its value should be \n",
    "            between 0 & 1.\n",
    "        K2 (float): The final value of the tranche. \n",
    "        beta (float): Correlation perameter. Its value should be between 0 and 1.\n",
    "        R (float): Recovery rate. Usually between 0 and 1.\n",
    "        Q (callable function): A function Q that takes in a dateime.date and\n",
    "            outputs a float from 0 to 1. It is assumed that Q(0) = 1 and Q is \n",
    "            decreasing. Represents survival curve of each credit.\n",
    "    \"\"\"\n",
    "    if Q(t) == 1:\n",
    "        return 1 # prevents infinity\n",
    "    def emin(K):\n",
    "    # Calculates E[min(L(T), K)] in LHP model\n",
    "        print(Q(t))\n",
    "        C = norm.ppf(1 - Q(t))\n",
    "        A = (1 / beta) * (C - sqrt(1 - beta * beta) * norm.ppf(K / (1 - R)))\n",
    "        return (1 - R) * mvn.mvndst(upper = [C, -1 * A],\n",
    "                                    lower = [0,0],\n",
    "                                    infin = [0,0], # set lower bounds = -infty\n",
    "                                    correl =  -1 * beta)[1] + K * norm.cdf(A)\n",
    "    return 1 - (emin(K2) - emin(K1)) / (K2 - K1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Gaussian Heterogenous Model\n",
    "---------------------------\n",
    "\n",
    "The tranche survival curve is given by \n",
    "\n",
    "$$\\begin{aligned}\n",
    "Q_{\\text{Gauss}} (t, K_1, K_2) & = 1 - \\frac{1}{K_2 - K_1} \\int_{- \\infty}^{+ \\infty} \\phi (z) f(z) dz \\\\\n",
    "f(z) &= \\sigma \\phi \\left(\\frac{\\mu - K_1}{\\sigma} \\right) + (\\mu - K_1) \\Phi \\left( \\frac{\\mu - K_1}{\\sigma} \\right) - (\\mu - K_2) \\Phi \\left( \\frac{\\mu - K_2}{\\sigma} \\right) - \\sigma \\phi \\left( \\frac{\\mu - K2}{\\sigma} \\right) \\\\\n",
    "\\mu &= \\frac{1}{N} \\sum_{i=1}^{N} p_{i}(t,z) F_i (1 - R_i) \\\\\n",
    "\\sigma^{2} &= \\frac{1}{N^2} \\sum_{i=1}^{N} p_i (t,z) (1 - p_i (t,z)) F_i^2 (1-R_i)^{2} \\\\\n",
    "p_{i}(t,z) &= \\Phi \\left( \\frac{C_i (t) - \\beta_i z}{\\sqrt{1 - \\beta_i^2}}\\right) \\\\\n",
    "C_{i} (t) &= \\Phi^{-1} (1 -Q_i (t))\n",
    "\\end{aligned}$$\n",
    "\n",
    "Here:\n",
    "\n",
    "* $K_1, K_2$ are the boundaries of the tranche (they are between 0 and 1).\n",
    "* $N$ is the number of credits\n",
    "* $F_i$ is the fractional face value of the $i$th credit.\n",
    "* $R_i$ is the recovery rate of the $i$th credit.\n",
    "* $\\beta_{i}$ is the $i$th correlation perameter\n",
    "* $Q_i$ is the survival curve of the $i$th credit.\n",
    "\n",
    "Unlike the LHP model, this is heterogenous in that each credit has distinct values of $ R_i, \\beta_i, Q_i$. Moreover, the values of $F_i$ becomes relevant."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "from scipy.integrate import quad\n",
    "def Q_gauss(t, K1, K2, Fs, Rs, betas, Qs):\n",
    "    \"\"\" Calculate the tranche survival probability in the Gaussian heterogenous model.\n",
    "    \n",
    "    Arguments:\n",
    "        t (float): Time. Positive.\n",
    "        K1 (float): Starting tranche value. Between 0 and 1.\n",
    "        K2 (float): Ending tranche value. Between 0 and 1.\n",
    "        Fs (list): List of fractional face values for each credit. Each entry must be\n",
    "            between 0 and 1.\n",
    "        Rs (list): List of recovery rates for each credit. Each entry must be between\n",
    "            0 and 1.\n",
    "        betas (list): Correlation perameters for each credit. Each entry must be between\n",
    "            0 and 1.\n",
    "        Qs (list): Survival curves for each credit. Each entry must be a callable function\n",
    "            that takes in a datetime.date argument and returns a number from 0 to 1.\n",
    "    \"\"\"\n",
    "    Cs = [norm.ppf(1 - q(t)) for q in Qs]\n",
    "    N = len(Fs) \n",
    "    def f(z):\n",
    "        ps = [norm.cdf((C - beta * z) / sqrt(1 - beta * beta)) for C, beta in zip(Cs, betas)]\n",
    "        mu = 1 / N * sum([p * F * (1 - R) for p, F, R in zip(ps, Fs, Rs)])\n",
    "        sigma_squared = 1 / N / N * sum([p * (1 - p) * F ** 2 * (1 - R) ** 2 for p, F, R in zip(ps, Fs, Rs)])\n",
    "        sigma = sqrt(sigma_squared)\n",
    "        return (sigma * norm.pdf((mu - K1) / sigma)\n",
    "                - sigma * norm.pdf((mu - K2) / sigma) \n",
    "                + (mu - K1) * norm.cdf((mu - K1) / sigma) \n",
    "                - (mu - K2) * norm.cdf((mu - K2) / sigma))\n",
    "    integral = quad(lambda z: f(z) * norm.pdf(z), -10, 10)[0]\n",
    "    return 1 - integral / (K2 - K1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Adjusted Binomial Model\n",
    "-----------------------\n",
    "\n",
    "The adjusted binomial model is given as \n",
    "\n",
    "$$\\begin{aligned}\n",
    "E[min(L(T),K)] &= \\sum_{k=0}^{N} h(k) \\min (Lk, K) \\\\\n",
    "h(k) &= \\int_{- \\infty}^{\\infty} \\phi (z) g(k) dz \\\\\n",
    "g(k) &= \\alpha f(k) \\text{ for } k \\neq l,u \\\\\n",
    "g(l) &= f(l) + (1 - \\alpha)(u - m) \\\\\n",
    "g(u) &= f(u) - (1 - \\alpha)(l - m) \\\\\n",
    "l &= \\text{floor} (m) \\\\\n",
    "m &= p N \\\\\n",
    "u &= l + 1 \\\\\n",
    "p &= \\frac{1}{N} \\sum_{i=1}^N \\frac{(1 - R_i)F_i}{L} p_i \\\\\n",
    "\\alpha &= \\frac{v_E N + (u - m)^2 -((l -m)^2 - (u -m)^2)(u -m)}\n",
    "{v_A N + (u - m)^2 -((l -m)^2 - (u -m)^2)(u -m)} \\\\\n",
    "v_E &= \\frac{1}{N^2} \\sum_{i=1}^{N} \\left( \\frac{(1-R_i)F_i}{L}\\right)^2 p_i(1 - p_i) \\\\\n",
    "v_A &= \\frac{p(1-p)}{N} \\\\\n",
    "f(k) &= \\frac{N!}{(N - k)! k!} p^k (1 - p)^{N - k} \\\\\n",
    "L &= \\frac{1}{N} \\sum_{i=1}^{N} (1 - R_i) F_i\n",
    "\\end{aligned}$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "def Q_adjbinom(t, K1, K2, Fs, Rs, betas, Qs):\n",
    "    if Qs[0](t) == 1:\n",
    "        return 1.0 # initial value -- avoids weird nan return\n",
    "    \n",
    "    N = len(Fs)\n",
    "    Cs = [norm.ppf(1 - Q(t)) for Q in Qs]\n",
    "    L = sum([(1 - R) * F for R, F in zip(Rs, Fs)]) / N\n",
    "    def choose(n, k): # Calculates binomial coeffecient: n choose k.\n",
    "        if k == 0 or k == n:\n",
    "            return 1\n",
    "        return choose(n - 1, k - 1) + choose(n - 1, k)\n",
    "    def g(k,z):\n",
    "        ps = [norm.cdf((C - beta * z) / sqrt(1 - beta * beta)) for C, beta in zip(Cs, betas)]\n",
    "        p_avg = sum([(1 - R) * F / L * p for R, F, p in zip(Rs, Fs, ps)]) / N\n",
    "        f = lambda k: choose(N, k) * p_avg ** k * (1 - p_avg) ** (N - k)\n",
    "        vA = p_avg * (1 - p_avg) / N\n",
    "        vE = 1 / N / N * sum([((1 - R) * F / L) ** 2 * p * (1 - p) for R, F, p in zip(Rs, Fs, ps)])\n",
    "        m = p_avg * N\n",
    "        l = int(m)\n",
    "        u = l + 1\n",
    "        o = (u - m) ** 2 + ((l - m) ** 2 - (u - m) ** 2) * (u - m)\n",
    "        alpha = (vE * N + o) / (vA * N + o)\n",
    "        if k == l:\n",
    "            return f(l) + (1 - alpha) * (u - m)\n",
    "        if k == u:\n",
    "            return f(u) - (1 - alpha) * (l - m)\n",
    "        return alpha * f(k)\n",
    "    I = lambda k: quad(lambda z: norm.pdf(z) * g(k, z), -10, 10)[0]\n",
    "    emin = lambda K: sum([I(k) * min(L * k, K) for k in range(0, N + 1)])\n",
    "    return 1 - (emin(K2) - emin(K1)) / (K2 - K1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Example\n",
    "-------"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "from numpy import exp\n",
    "from datetime import date, timedelta\n",
    "K1 = 0.03\n",
    "K2 = 0.07\n",
    "Fs = [0.3, 0.8]\n",
    "Rs = [0.40, 0.60]\n",
    "def expdecay(today, rate):\n",
    "    return lambda t: exp(-1 * (t - today).days / 365 * rate)\n",
    "today = date(2012,1, 1)\n",
    "Qs = [expdecay(today, 0.0120), expdecay(today, 0.0160)]\n",
    "betas = [0.30, 0.40]\n",
    "tvalues = [today + timedelta(days = 30) * n for n in range(37)] #3 years\n",
    "# LHP perameters average the other perameters\n",
    "R = 0.50\n",
    "Q = expdecay(today, 0.0140)\n",
    "beta = 0.35"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.998849976853\n",
      "0.998849976853\n",
      "0.997701276258\n",
      "0.997701276258\n",
      "0.996553896696\n",
      "0.996553896696\n",
      "0.995407836647\n",
      "0.995407836647\n",
      "0.994263094594\n",
      "0.994263094594\n",
      "0.993119669021\n",
      "0.993119669021\n",
      "0.991977558413\n",
      "0.991977558413\n",
      "0.990836761259\n",
      "0.990836761259\n",
      "0.989697276048\n",
      "0.989697276048\n",
      "0.988559101272\n",
      "0.988559101272\n",
      "0.987422235423\n",
      "0.987422235423\n",
      "0.986286676996\n",
      "0.986286676996\n",
      "0.985152424487\n",
      "0.985152424487\n",
      "0.984019476395\n",
      "0.984019476395\n",
      "0.98288783122\n",
      "0.98288783122\n",
      "0.981757487463\n",
      "0.981757487463\n",
      "0.980628443627\n",
      "0.980628443627\n",
      "0.979500698218\n",
      "0.979500698218\n",
      "0.978374249742\n",
      "0.978374249742\n",
      "0.977249096708\n",
      "0.977249096708\n",
      "0.976125237626\n",
      "0.976125237626\n",
      "0.975002671008\n",
      "0.975002671008\n",
      "0.973881395367\n",
      "0.973881395367\n",
      "0.972761409219\n",
      "0.972761409219\n",
      "0.971642711082\n",
      "0.971642711082\n",
      "0.970525299473\n",
      "0.970525299473\n",
      "0.969409172914\n",
      "0.969409172914\n",
      "0.968294329925\n",
      "0.968294329925\n",
      "0.967180769032\n",
      "0.967180769032\n",
      "0.96606848876\n",
      "0.96606848876\n",
      "0.964957487636\n",
      "0.964957487636\n",
      "0.963847764189\n",
      "0.963847764189\n",
      "0.96273931695\n",
      "0.96273931695\n",
      "0.96163214445\n",
      "0.96163214445\n",
      "0.960526245225\n",
      "0.960526245225\n",
      "0.959421617809\n",
      "0.959421617809\n"
     ]
    }
   ],
   "source": [
    "# Takes FOREVER\n",
    "lhpcurve = [Q_lhp(t, K1, K2, R, beta, Q) for t in tvalues]\n",
    "adjointbinomialcurve = [Q_adjbinom(t, K1, K2, Fs, Rs, betas, Qs) for t in tvalues]\n",
    "gaussiancurve = [Q_gauss(t, K1, K2, Fs, Rs, betas, Qs) for t in tvalues]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<function matplotlib.pyplot.show>"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\nJ1VTTqJGg7uISAMod+9eaRkRkQZQyUSNBncRkTpRyUSNBncRkTpRyUSNau4iInVCNXcRkSbUtrCN\n3rW9pHcc+sJZAAAJ9UlEQVSnSeVSpHeniw7suYEc7avaJ3wt7bmLiDSQUXv3f4n23EVEmsGYRM04\nYg3uZrbUzJ4zsxfM7Koi6w83swfM7Ekz22JmyyPr5pjZP5rZVjN7xsxOL/OziIhIqGiipoiSg7uZ\nzQDWAmcDJwEXmNnxBc1WAE+6+weAFPB1M5sZrrsJuN/dTwBOBbbG/RC1ls1ma92FotSv+OqxT6B+\nlaMe+5RXi74VTdQUEWfPfRGwzd13uPtbwAZgWUGb14BZ4f1ZwM/d/W0zmw2c6e53Arj72+6+K+Zn\nqLl6/aFSv+Krxz6B+lWOeuxTXi36llmdIbE5UXKAjzO4zwNejjx+JVwW9bfASWY2BGwGLguXtwE/\nM7M7zWyjma0zs3fG+QAiIjJWNFEzkUodUP0ysNnd5wKnAbea2SHATOB3gFvd/XeA/wSurtB7ioi0\npLaFbay/ef3Ejdx9whuwGHgw8vhq4KqCNvcDH4k8/h7wIeBIoD+y/KPAd8Z5H9dNN910062823hj\nd/6g50SeAI41swXAq8D5wAUFbbYCZwGPm9mRwPsIBvWdZvaymb3P3V8APg48W+xNxstqiohI+UoO\n7u6+z8xWAA8RlHFud/etZnZpsNrXAdcCd5rZZsCAL7n7zvAlVgE9ZnYg0A98bjo+iIiIjKibM1RF\nRKRyJnVA1cx2T/WNzezy8KSmJ82s18yOjqy7KDxh6nkz+2xk+Z+Y2TYz22dmh5nZfjP7lpldaGab\nw9tbZvZIBfp3lpn9KHzNJ8wsFVn3O2b2VNjHGyPLzzSzH4d9ONfM/tzMng4/xx4zezH8vJ+qZb8i\ny980sx+EJ55Nql8V3o6fCD/XprCvP5jc/9Ko/k31/6sn3Iabw/+nrWHy62kzu6z4u057n6LbcE+4\nfNJ9quQ2jKw/3czczH5Ybn+K9K+S23CjmX3YzGZZUDK+uUZ9OrfIa06pT2OUOqA6zsHPXZN5XsFr\nfAx4R3j/fwAbwvu/CWwH5gCH5u+H604FjiEo7xwG7AY2AmeG7ZcCLwI7K9C/U4GjwvsnAa9E1v07\n8OHIweSzw/vHACcDdxEceH6coPR1LEFq6Cjgt4EhYHaN+nVupP1uIBHen1S/KrwdDw3XLyU4NvNm\n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\n2YZ9PP8AAAAASUVORK5CYII=\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x10808ef98>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "import matplotlib.pyplot as plt\n",
    "plt.plot(tvalues, lhpcurve, 'ro', #red\n",
    "         tvalues, adjointbinomialcurve, 'bo', #blue\n",
    "         tvalues, gaussiancurve, 'go' #green\n",
    "         )\n",
    "plt.show"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "37\n"
     ]
    },
    {
     "ename": "TypeError",
     "evalue": "unsupported operand type(s) for -: 'list' and 'datetime.date'",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-8-77f018d8785e>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m     11\u001b[0m \u001b[0mCDS1\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mCDS\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtoday\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mtoday\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmaturity\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmaturity\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mremaining_payments\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mremaining_payments\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mR\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mR\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mZ\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mZ\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mQ\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlhpcurve\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     12\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 13\u001b[0;31m \u001b[0mCDS1\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mparSpread\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mN\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mN\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m<ipython-input-1-7538f54f206a>\u001b[0m in \u001b[0;36mparSpread\u001b[0;34m(self, N)\u001b[0m\n\u001b[1;32m     58\u001b[0m                 \u001b[0mprotection\u001b[0m \u001b[0mleg\u001b[0m \u001b[0mintegral\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     59\u001b[0m         \"\"\"\n\u001b[0;32m---> 60\u001b[0;31m         \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mprotectionLegPV\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mN\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrpv01\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m<ipython-input-1-7538f54f206a>\u001b[0m in \u001b[0;36mprotectionLegPV\u001b[0;34m(self, N)\u001b[0m\n\u001b[1;32m     43\u001b[0m             \u001b[0mN\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mint\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0moptional\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mThe\u001b[0m \u001b[0mnumber\u001b[0m \u001b[0mof\u001b[0m \u001b[0mnodes\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mcalculating\u001b[0m \u001b[0mthe\u001b[0m \u001b[0mintegral\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     44\u001b[0m         \"\"\"\n\u001b[0;32m---> 45\u001b[0;31m         \u001b[0mdelta\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmaturity\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtoday\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdays\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0mN\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     46\u001b[0m         \u001b[0mdays\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mtoday\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mtimedelta\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdays\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdelta\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0mn\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mn\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mN\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     47\u001b[0m         \u001b[0;31m#print(days)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mTypeError\u001b[0m: unsupported operand type(s) for -: 'list' and 'datetime.date'"
     ]
    }
   ],
   "source": [
    "## Test Spreads\n",
    "maturity = tvalues\n",
    "remaining_payments = tvalues\n",
    "Z = expdecay(today, 0.0140)\n",
    "\n",
    "#print(lhpcurve[1])\n",
    "N = len(lhpcurve)\n",
    "print(N)\n",
    "#print(today)\n",
    "#print(maturity)\n",
    "CDS1 = CDS(today=today, maturity = maturity, remaining_payments = remaining_payments, R = R, Z = Z, Q = lhpcurve)\n",
    "\n",
    "CDS1.parSpread(N=N)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
